﻿using Entity;
using Struct;
using System;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace FastCopyWin
{

    public partial class MainWindow : Window
    {
        // 当前窗口
        WindowData my = new(IntPtr.Zero);
        // 焦点窗口
        WindowData force = new(IntPtr.Zero);

        // 工作视图
        public ClipboardDataViewModel dynamicDataViewModel;
        public ClipboardDataViewModel constDataViewModel;

        // 工作配置
        private readonly ConfigData configData = ConfigManagementService.GetInstance().GetCurrentConfig();

        public MainWindow()
        {
            // 初始化界面组件
            InitializeComponent();
            // 初始化数据
            InitializeDataViewModel();
            // 初始化主界面样式
            InitializeWindowStyle();
            // 初始化快捷键
            InitializeShortcutKey();
            // 默认打开显示动态数据界面
            ShowDynamicWindow();
            // 关闭程序
            this.Closing += (s, e) => { Environment.Exit(0); };
        }

        private void InitializeShortcutKey()
        {
            // 快捷键 显示历史数据界面
            KeyboardUtils.ControlKeyEnum dynamicControlKey = Enum.Parse<KeyboardUtils.ControlKeyEnum>(configData.DynamicDataShortcutKey[0]);
            Keys dynamicKey = Enum.Parse<Keys>(configData.DynamicDataShortcutKey[1]);
            KeyboardUtils.AddKeyboardAction(dynamicControlKey, dynamicKey, ShowDynamicWindow);

            // 快捷键 显示片段数据界面
            KeyboardUtils.ControlKeyEnum constControlKey = Enum.Parse<KeyboardUtils.ControlKeyEnum>(configData.ConstDataShortcutKey[0]);
            Keys constKey = Enum.Parse<Keys>(configData.ConstDataShortcutKey[1]);
            KeyboardUtils.AddKeyboardAction(constControlKey, constKey, ShowConstWindow);

            // 默认快捷键 将数据复制到剪切板
            KeyboardUtils.AddKeyboardAction(Keys.Enter, CoverClipboardData);
            // 默认快捷键 鼠标点击在非界面上 则隐藏界面
            MouseUtils.AddMouseAction(MouseUtils.KeyEnum.LEFT_KEY, HideWindow);
            // 默认快捷键 ESC 退出界面
            KeyboardUtils.AddKeyboardAction(Keys.Escape, HideWindow);

            // 默认快捷键 将历史的第一条记录放入片段
            KeyboardUtils.AddKeyboardAction(KeyboardUtils.ControlKeyEnum.CTRL, Keys.N, CopyDataToConst);
        }

        private void InitializeWindowStyle()
        {
            this.Title = "FastCopy";
            DeviceUtils.GetDeviceCaps(out float w, out float h);
            this.Height = h - (h / AppConst.GOLDEN_RATIO_COEFFICIENT);
            this.Width = AppConst.GOLDEN_RATIO_COEFFICIENT * this.Height - this.Height;
            // 显示位置跟随鼠标
            POINT point = MouseUtils.GetCursorPosition();
            double scale = DeviceUtils.GetPositionScale();
            double left = point.x * scale;
            double top = point.y * scale;
            int buffer = 5;
            this.Top = top + Height + buffer > h ? top - Height : top;
            this.Left = left + Width + buffer > w ? left - Width : left;
        }

        private void InitializeDataViewModel()
        {
            dynamicDataViewModel = new ClipboardDataViewModel(configData.DynamicDataFilePath, configData.MaxRecord);
            constDataViewModel = new ClipboardDataViewModel(configData.ConstDataFilePath, configData.MaxRecord);
        }

        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);
            HwndSource source = PresentationSource.FromVisual(this) as HwndSource ?? throw new SystemException();
            ClipboardListenerService.GetInstance().AddClipboardListener(source, ClipboardChangeData);
        }

        private void Window_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                DragMove();
            }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            my = new WindowData(new WindowInteropHelper(this).Handle);
            my.ThreadId = Win32Api.GetWindowThreadProcessId(my.Hwnd, IntPtr.Zero);
        }


        void ClipboardChangeData(ClipboardDataType type, Object data) 
        {
            string clipboardData = "";
            switch (type) 
            {
                case ClipboardDataType.IMAGE:
                    if (data is BitmapSource bitmapSource)
                    {
                        // 共性问题 会丢失透明度 暂不解决
                        WriteableBitmap writeableBitmap = SundayLiUtils.CreateByOpacityColor(bitmapSource);
                        clipboardData = SundayLiUtils.WriteableBitmapToBase64(writeableBitmap);
                    }
                    break;
                case ClipboardDataType.TEXT:
                    clipboardData = data as string ?? clipboardData;
                    break;
                default: break;
            }
            dynamicDataViewModel.AddUnlikeFirstData(new ClipboardData(type, clipboardData));
        }

        private void CoverClipboardData()
        {
            if (!this.IsActive) return;
            ClipboardDataViewItem item = (ClipboardDataViewItem)lvClipboard.SelectedItem;
            ClipboardListenerService.GetInstance().SetClipboardData(item.Data);
            HideWindow(true);
            DeviceUtils.NotifySystemPaste(force);
        }

        private void ShowWindow(bool isSelectFirst) 
        {
            // 记录显示前窗口句柄
            DeviceUtils.GetCurrentForeWindowInfo(out force);
            // 在多显示器下 各个屏幕的宽高是不一样的 最好重新计算主样式
            InitializeWindowStyle();
            // 强制将本窗口放置屏幕最前 本质是附加线程然后抢焦点
            Win32Api.AttachThreadInput(force.ThreadId, my.ThreadId, true);
            this.Show();
            this.Activate();
            this.Topmost = true;
            Win32Api.AttachThreadInput(force.ThreadId, my.ThreadId, false);
            this.Topmost = false;

            if (isSelectFirst)
            {
                lvClipboard.SelectedIndex = 0;
            }

            if (lvClipboard.ItemContainerGenerator.ContainerFromItem(lvClipboard.SelectedItem) is System.Windows.Controls.ListViewItem item) 
            {
                // 将焦点放在选中的 item 上
                Keyboard.Focus(item);
            }
            
            // 淡入动画
            DoubleAnimation doubleAnimation = new()
            {
                From = 0.0,
                To = 0.88,
                Duration = new Duration(TimeSpan.FromSeconds(0.2))
            };
            Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath(Rectangle.OpacityProperty));
            Storyboard storyboard = new();
            storyboard.Children.Add(doubleAnimation);
            storyboard.Begin(this);
        }

        private void ShowConstWindow()
        {
            lvClipboard.DataContext = constDataViewModel.ClipboardDataViewItemList;
            lvClipboard.Height = this.Height;
            lvClipboardName.Text = "片段";
            ShowWindow(false);
        }

        private void ShowDynamicWindow()
        {
            lvClipboard.DataContext = dynamicDataViewModel.ClipboardDataViewItemList;
            lvClipboard.Height = this.Height;
            lvClipboardName.Text = "历史";
            ShowWindow(true);
        }

        private void HideWindow()
        {
            HideWindow(false);
        }

        private void HideWindow(bool isForceHide)
        {
            if (isForceHide || !IsMouseOver)
            {
                // 隐藏动画
                DoubleAnimation myDoubleAnimation = new()
                {
                    From = 0.0,
                    To = 0.0,
                    Duration = new Duration(TimeSpan.FromSeconds(0))
                };
                Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.OpacityProperty));
                Storyboard storyboard = new();
                storyboard.Children.Add(myDoubleAnimation);
                storyboard.Begin(this);
            }
        }

        private void CopyDataToConst()
        {
            if (dynamicDataViewModel.GetFirstData() is ClipboardData data)
            {
                constDataViewModel.AddUnlikeFirstData(data);
            }
        }
    }
}
